#undef    _FILE_OFFSET_BITS   
#define   _FILE_OFFSET_BITS   64   
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include "locketdef.h"
#include "locketerrno.h"
#include "locketcipher.h"
#include "lockethmac.h"
#include "locketaes.h"
#include "locketrsa.h"
#include "locketdigest.h"
#include "locketfilecrypt.h"
#include "locketstreamcrypt.h"
#ifdef APPLE
#include <spawn.h>
#endif

#ifdef WIN32
#define ENCRYPTED_FILE  "e:\\test\\file_encrypt.txt"
#define DECRYPTED_FILE  "e:\\test\\file_decrypt.txt"
#define ENCRYPTED_STREAM  "e:\\test\\stream_encrypt.txt"
#define DECRYPTED_STREAM  "e:\\test\\stream_decrypt.txt"

#else
#define ENCRYPTED_FILE  "file_encrypt.txt"
#define DECRYPTED_FILE  "file_decrypt.txt"
#define ENCRYPTED_STREAM  "stream_encrypt.txt"
#define DECRYPTED_STREAM  "stream_decrypt.txt"

#endif

#ifdef WIN32
#define BASE64_DECODE(input)
#elif APPLE
#define BASE64_DECODE(input)\
{\
    printf ("[BASE64-DECODE]\n");\
    char __buffer[1024*2] = {0};\
    snprintf (__buffer, sizeof (__buffer), "echo \"%s\" | base64 -D | hexdump ", input);\
    pid_t child_pid;\
    posix_spawn(&child_pid, __buffer, NULL, NULL, NULL, NULL);\
}
#elif UNIX
#define BASE64_DECODE(input)\
{\
    printf ("[BASE64-DECODE]\n");\
    char __buffer[1024*2] = {0};\
    snprintf (__buffer, sizeof (__buffer), "echo \"%s\" | base64 -d | hexdump ", input);\
    system(__buffer);\
}
#else
#define BASE64_DECODE(input)
#endif


char *gpcFileName = NULL;
char gbuffer[1024*20] = {0};
char gbuffer2[1024*20] = {0};
unsigned char gszBuffer[1024*20] = {0};
int gInputEncode = 0;
void TEST_Output (char *pcAlgoName, int encode, unsigned char* pucOutput, int outputlen)
{
    int i = 0;
    if (encode  == 2)
    {
        printf ("[%s] to Byte:", pcAlgoName);
        for (i = 0; i < outputlen; i ++)
        {
            printf ("0x%.02x ", pucOutput[i]);
        }
        printf ("\n");
    }
    else if (encode  == 1)
    {
        printf ("[%s] to Base64:", pcAlgoName);
        printf ("%s\n", pucOutput);
    }
    else if (encode  == 0)
    {
        printf ("[%s] to Hex:", pcAlgoName);
        printf ("%s\n", pucOutput);
    }

}

void TEST_Hash (char *pcAlgoName, char *input, int inputlen)
{
    int iErr = ERR_COMMON_SUCCESS;

    if (NULL == pcAlgoName)
    {
        printf ("invalid param\n");
        return;
    }
    char *pcInputTmp = input;
    if (NULL == pcInputTmp)
    {
        pcInputTmp = "hello,world";
    }


    /* HASH test */
    CIPHER_HASH_S stHash;
    memset (&stHash, 0, sizeof (stHash));

    snprintf (stHash.szAlgoName, sizeof (stHash.szAlgoName), "%s", pcAlgoName);
    stHash.pucOutput = gszBuffer;
    stHash.pucInput = (unsigned char*) pcInputTmp;
    stHash.iInputLen = inputlen;
    stHash.iInputEncode = gInputEncode;

    stHash.iOutputEncode = 2;
    iErr = LOCKET_CIPHER_Digest(&stHash);
    if (ERR_COMMON_SUCCESS != iErr)
    {
        printf ("LOCKET_CIPHER_Digest iError, line:%d, iErr:%d\n", __LINE__, iErr);
        return ;
    }
    TEST_Output (pcAlgoName,stHash.iOutputEncode, stHash.pucOutput,  stHash.iOutputLen);


    stHash.iOutputEncode = 0;
    iErr = LOCKET_CIPHER_Digest(&stHash);
    if (ERR_COMMON_SUCCESS != iErr)
    {
        printf ("LOCKET_CIPHER_Digest iError, line:%d, iErr:%d\n", __LINE__, iErr);
        return ;
    }
    TEST_Output (pcAlgoName,stHash.iOutputEncode, stHash.pucOutput,  stHash.iOutputLen);

    stHash.iOutputEncode = 1;
    iErr = LOCKET_CIPHER_Digest(&stHash);
    if (ERR_COMMON_SUCCESS != iErr)
    {
        printf ("LOCKET_CIPHER_Digest iError, line:%d, iErr:%d\n", __LINE__, iErr);
        return ;
    }
    TEST_Output (pcAlgoName,stHash.iOutputEncode, stHash.pucOutput,  stHash.iOutputLen);

    BASE64_DECODE (stHash.pucOutput);

    return;

}

void TEST_Hmac (char *pcAlgoName, char *input, int inputlen)
{
    int iErr = ERR_COMMON_SUCCESS;

    /* hmac key*/
    unsigned char szHmacKey[] = "dGhpcyBpcyBobWFjIGtleQ==";  //"this is hmac key"

    CIPHER_HMAC_S stHmac;
    memset (&stHmac, 0, sizeof (stHmac));

    snprintf (stHmac.szAlgoName, sizeof (stHmac.szAlgoName), "%s", pcAlgoName);
    stHmac.pucKey  = szHmacKey;
    stHmac.iKeyLen = strlen ((char*) stHmac.pucKey);

    stHmac.pucInput = (unsigned char*) input;
    stHmac.iInputEncode = gInputEncode;
    stHmac.iInputLen = inputlen;

    stHmac.pucOutput = gszBuffer;

    /* hmac 计算 */
    stHmac.iOutputEncode = 2;
    iErr = LOCKET_CIPHER_Hmac (&stHmac);
    if (ERR_COMMON_SUCCESS != iErr)
    {
        printf ("LOCKET_CIPHER_Hmac iError, line:%d, iErr:%d\n", __LINE__, iErr);
        return ;
    }
    TEST_Output (pcAlgoName,stHmac.iOutputEncode, stHmac.pucOutput,  stHmac.iOutputLen);

    stHmac.iOutputEncode = 0;
    iErr = LOCKET_CIPHER_Hmac (&stHmac);
    if (ERR_COMMON_SUCCESS != iErr)
    {
        printf ("LOCKET_CIPHER_Hmac iError, line:%d, iErr:%d\n", __LINE__, iErr);
        return ;
    }
    TEST_Output (pcAlgoName,stHmac.iOutputEncode, stHmac.pucOutput,  stHmac.iOutputLen);

    stHmac.iOutputEncode = 1;
    iErr = LOCKET_CIPHER_Hmac (&stHmac);
    if (ERR_COMMON_SUCCESS != iErr)
    {
        printf ("LOCKET_CIPHER_Hmac iError, line:%d, iErr:%d\n", __LINE__, iErr);
        return ;
    }
    TEST_Output (pcAlgoName,stHmac.iOutputEncode, stHmac.pucOutput,  stHmac.iOutputLen);

    BASE64_DECODE (stHmac.pucOutput);

    return;
}

void TEST_AES (char *pcAlgoName, char *input, int inputlen)
{
    int iErr = ERR_COMMON_SUCCESS;

    /* key */
    unsigned char szKey[] = "dGhpcyBpcyBhZXMga2V5";  //"this is hmac key"
    /* iv */
    unsigned char szIv[] = "dGhpcyBpcyBhZXMgaXY="; //"this is iv"

    CIPHER_AES_S stAes;
    memset (&stAes, 0, sizeof (stAes));

    snprintf (stAes.szAlgoName, sizeof (stAes.szAlgoName), "%s", pcAlgoName);
    stAes.pucKey  = szKey;
    stAes.pucIv = szIv;

    stAes.pucInput = (unsigned char*) input;
    stAes.iInputEncode = gInputEncode;
    stAes.iInputLen = inputlen;

    stAes.pucOutput = gszBuffer;
    stAes.iMode = 1;

    /* hmac 计算 */
    stAes.iOutputEncode = 2;
    iErr = LOCKET_CIPHER_AESCrypt (&stAes);
    if (ERR_COMMON_SUCCESS != iErr)
    {
        printf ("LOCKET_CIPHER_AESCrypt iError, line:%d, iErr:%d\n", __LINE__, iErr);
        return ;
    }
    TEST_Output (pcAlgoName,stAes.iOutputEncode, stAes.pucOutput,  stAes.iOutputLen);

    /* 解码 */
    stAes.iMode = 0;
    stAes.iInputEncode = stAes.iOutputEncode;
    stAes.iInputLen = stAes.iOutputLen;
    stAes.iOutputEncode = 2;
    stAes.pucInput = stAes.pucOutput;
    memset (gbuffer2, 0, sizeof (gbuffer2));
    stAes.pucOutput = (unsigned char*) gbuffer2;
    iErr = LOCKET_CIPHER_AESCrypt (&stAes);
    if (ERR_COMMON_SUCCESS != iErr)
    {
        printf ("LOCKET_CIPHER_AESCrypt iError, line:%d, iErr:%d\n", __LINE__, iErr);
        return ;
    }

    printf ("decode:%s\n", stAes.pucOutput);

    stAes.iOutputEncode = 0;
    iErr = LOCKET_CIPHER_AESCrypt (&stAes);
    if (ERR_COMMON_SUCCESS != iErr)
    {
        printf ("LOCKET_CIPHER_AESCrypt iError, line:%d, iErr:%d\n", __LINE__, iErr);
        return ;
    }
    TEST_Output (pcAlgoName,stAes.iOutputEncode, stAes.pucOutput,  stAes.iOutputLen);


    stAes.iOutputEncode = 1;
    iErr = LOCKET_CIPHER_AESCrypt (&stAes);
    if (ERR_COMMON_SUCCESS != iErr)
    {
        printf ("LOCKET_CIPHER_AESCrypt iError, line:%d, iErr:%d\n", __LINE__, iErr);
        return ;
    }
    TEST_Output (pcAlgoName,stAes.iOutputEncode, stAes.pucOutput,  stAes.iOutputLen);

    BASE64_DECODE (stAes.pucOutput);

    return;
}

void TEST_RSA (char *input, int inputlen)
{
    int iErr = 0;
    CIPHER_RSA_S stRSA;
	memset (&stRSA, 0, sizeof (stRSA));
    memset (gszBuffer, 0, sizeof (gszBuffer));

    stRSA.pucInput = (unsigned char*)input;
    stRSA.iInputLen = inputlen;
    stRSA.iInputEncode = 2;
    stRSA.iOutputEncode = 2;
    stRSA.pucOutput = gszBuffer ;
    
    /* encrypt */
    FILE *publicfp = fopen ("public1024.pem", "rb");
    if (NULL == publicfp)
    {
        printf ("open file failed\n");
        return ;
    }

	char szPublicKey[1024*2] = {0};
    int readn = fread (szPublicKey, 1, sizeof(szPublicKey), publicfp);
    stRSA.pucKey = (unsigned char*)szPublicKey;

    iErr = LOCKET_CIPHER_RSAEncrypt(&stRSA);
    if (ERR_COMMON_SUCCESS != iErr)
    {
        printf ("LOCKET_CIPHER_RSAEncrypt iError, line:%d, iErr:%d\n", __LINE__, iErr);
        return ;
    }   
    fclose (publicfp);

    memset (gbuffer2, 0, sizeof (gbuffer2));
    stRSA.pucInput = stRSA.pucOutput;
    stRSA.iInputLen = stRSA.iOutputLen;
    printf ("stRSA.iOutputLen:%d\n", stRSA.iOutputLen);

    stRSA.pucOutput = (unsigned char*) gbuffer2;
    /* decrypt */
    FILE *privatefp = fopen ("private1024.pem", "rb");
    if (NULL == privatefp)
    {
        printf ("open file failed\n");
        return ;
    }

    char szPrivateKey[1024*2] = {0};
    readn = fread (szPrivateKey, 1, sizeof(szPrivateKey), privatefp);
    stRSA.pucKey = (unsigned char*)szPrivateKey;
    iErr = LOCKET_CIPHER_RSADecrypt(&stRSA);
    if (ERR_COMMON_SUCCESS != iErr)
    {
        printf ("LOCKET_CIPHER_RSADecrypt iError, line:%d, iErr:%d\n", __LINE__, iErr);
        return ;
    }    

    fclose (privatefp);
    printf ("stRSA.putOutput:%s\n", stRSA.pucOutput);
	
    return;
}

int buffer_crypt (char *pcArg)
{

    gpcFileName = pcArg;

    FILE *fp = fopen (gpcFileName, "rb");
    if (NULL == fp)
    {
        printf ("open file failed\n");
        return 0;
    }
    if (0 == strncmp (gpcFileName, "binary.txt", strlen(gpcFileName)))
    {
        gInputEncode = 2;
    }
    else if (0 == strncmp (gpcFileName, "hex.txt", strlen(gpcFileName)))
    {
        gInputEncode = 0;
    }
    else if (0 == strncmp (gpcFileName, "base64.txt", strlen(gpcFileName)))
    {
        gInputEncode = 1;
    }
    else
    {
        printf ("file name error\n");
        return 0;
    }
    int readn = 0;
    int sum = 0;
    while (!feof(fp))
    {
        readn = fread (gbuffer+sum, 1, 1024, fp);
        if (readn <= 0)
        {
            if (0 != ferror (fp))
            {
                printf ("read file error\n");
                return 0;
            }
        }
        sum += readn;
    }

    if (0 == sum)
    {
        return 0;
    }
#if 1
    if (sum > 0)
    {
        if (gbuffer [ sum - 1] == '\n')
        {
            gbuffer [sum - 1] = 0;
            sum --;
        }
    }
#endif
    /* Hash Test */
    {
        printf ("\n");
        printf ("Hash test ==========================================\n");
        // TEST_Hash ("MD4", gbuffer, sum);
        TEST_Hash ("MD5", gbuffer, sum);
        TEST_Hash ("SHA1", gbuffer, sum);
        //  TEST_Hash ("SHA224", gbuffer, sum);
        TEST_Hash ("SHA256", gbuffer, sum);
        //  TEST_Hash ("SHA384", gbuffer, sum);
        TEST_Hash ("SHA512", gbuffer, sum);
    }

    /* Hmac Test */
    {
        printf ("\n");
        printf ("Hmac test ==========================================\n");
        TEST_Hmac ("MD5", gbuffer, sum);
        TEST_Hmac ("SHA1", gbuffer, sum);
        TEST_Hmac ("SHA224", gbuffer, sum);
        TEST_Hmac ("SHA256", gbuffer, sum);
        TEST_Hmac ("SHA384", gbuffer, sum);
        TEST_Hmac ("SHA512", gbuffer, sum);

        //openssl dgst -SHA1  -hmac "this is hmac key" binary.txt
    }

    /* AES Test */
    {
        printf ("\n");
        printf ("AES test ==========================================\n");
        TEST_AES ("AES-128-CFB", gbuffer, sum);
        TEST_AES ("AES-256-CFB", gbuffer, sum);
        TEST_AES ("AES-128-CBC", gbuffer, sum);
        TEST_AES ("AES-256-CBC", gbuffer, sum);

        //openssl enc -aes-128-cfb -in binary.txt -K 7468697320697320616573206b6579 -iv 7468697320697320616573206976 | hexdump
    }

    /* RSA Test */
    {
        printf("\n");
        printf ("RSA test ==========================================\n");

        TEST_RSA (gbuffer, sum);


    }

    fclose (fp);
    fp = NULL;
    return 0;
}

/**
* @Function:EncryptCBFunc
* @Author: guojianchuan/max
* @Date: 2016-07-19
* @Description: 加密回调函数
* @caution: 
*/
static int EncryptCBFunc (int iMsg, void* pParam)
{
    static FILE *fp = NULL;
    int iErr = ERR_COMMON_SUCCESS;

    switch (iMsg)
    {
        case MSG_CRYPT_DATA:
        case MSG_CRYPT_FINISH:
        {
            if (NULL == fp)
            {
                fp = fopen (ENCRYPTED_FILE, "wb+");
                if (NULL == fp)
                {
                    iErr = ERR_COMMON_FILE_OPER_FAILED;
                    break;
                }
            }

            if (MSG_CRYPT_FINISH == iMsg)
            {
                fclose (fp);
                fp = NULL;
                break;
            }

            if (NULL == pParam)
            {
                iErr = ERR_COMMON_INVALID_PARAM;
                break;
            }

            CB_PARAM_S *pstParam = pParam;
            if (0 == pstParam->iParamLen)
            {
                break;
            }

            int iWriteLen = fwrite (pstParam->pcData, 1, pstParam->iParamLen, fp);
            if (iWriteLen < 0)
            {
                iErr = ERR_COMMON_FILE_OPER_FAILED;
                break;
            }
            break;
        }
        default:
        {
            break;
        }
    }

    return iErr;
}

/**
* @Function:ProgessCBFunc
* @Author: guojianchuan/max
* @Date: 2016-07-19
* @Description: 加解密进度反馈
* @caution: 
*/
static int ProgessCBFunc (int iMsg, void* pParam)
{
    (void) iMsg;

    if (NULL == pParam)
    {
        return 0;
    }

    float fPercent = *((float*) pParam);

    //printf ("current percent %.2f\n", fPercent * 100);

    return 0;
}

static int DecryptCBFunc (int iMsg, void* pParam)
{
    int iErr = ERR_COMMON_SUCCESS;
    static FILE *fp = NULL;

    switch (iMsg)
    {
        case MSG_CRYPT_DATA:
        case MSG_CRYPT_FINISH:
        {
            if (NULL == fp)
            {
                fp = fopen (DECRYPTED_FILE, "wb+");
                if (NULL == fp)
                {
                    iErr = ERR_COMMON_FILE_OPER_FAILED;
                    break;
                }
            }

            if (MSG_CRYPT_FINISH == iMsg)
            {
                fclose (fp);
                fp = NULL;
                break;
            }

            CB_PARAM_S *pstParam = (CB_PARAM_S*) pParam;
            if ((NULL == pstParam) || (0 == pstParam->iParamLen))
            {
                iErr = ERR_COMMON_INVALID_PARAM;
                break;
            }

            int iWriteLen = 0;

            iWriteLen = fwrite (pstParam->pcData, 1, pstParam->iParamLen, fp);
            if (iWriteLen <= 0)
            {
                iErr = ERR_COMMON_FILE_OPER_FAILED;
                break;
            }

            break;
        }
        default:
        {
            break;
        }
    }

    return iErr;
}
void file_crypt (char *pcParam)
{
    int iErr = ERR_COMMON_SUCCESS;
    CIPHER_FILE_S stFileCrypt = {0};
    META_S stMeta = {0};

    stFileCrypt.pcFileName = pcParam;
    stFileCrypt.pfCryptCBFunc = EncryptCBFunc;
    stFileCrypt.pfProgressCBFunc = ProgessCBFunc;

    snprintf (stMeta.szId, sizeof (stMeta.szId), "%s", "this is id");
    snprintf (stMeta.szOwner, sizeof (stMeta.szId), "%s", "this is owner");
    stMeta.iVersion = 1;
    stMeta.iBlockSize = 1024;
    stMeta.iOffLine = 1;

    snprintf (stMeta.stCipher.szAlgorithm, sizeof (stMeta.stCipher.szAlgorithm), "%s", "AES");
    snprintf (stMeta.stCipher.szMode, sizeof (stMeta.stCipher.szMode), "%s", "CFB");
    snprintf (stMeta.stCipher.szPadding, sizeof (stMeta.stCipher.szPadding), "%s", "NoPadding");
    snprintf ((char*) stMeta.stCipher.szKey, sizeof (stMeta.stCipher.szKey), "%s", "this is key");
    snprintf ((char*) stMeta.stCipher.szIv, sizeof (stMeta.stCipher.szIv), "%s", "this is Iv");

    stMeta.stThumb.iExistes = 1;
    stMeta.stThumb.iSize = 2048;

    printf ("file encrypt \n");
    iErr = LOCKET_CIPHER_FileEncrypt(&stFileCrypt, &stMeta);
    if (ERR_COMMON_SUCCESS != iErr)
    {
        printf ("file encrypt failed, iErr:%d\n",iErr);
    }

    stFileCrypt.pcFileName = ENCRYPTED_FILE;
    stFileCrypt.pfCryptCBFunc = DecryptCBFunc;
    printf ("file decrypt \n");
    iErr = LOCKET_CIPHER_FileDecrypt (&stFileCrypt);
    if (ERR_COMMON_SUCCESS != iErr)
    {
        printf ("file decrypt failed, iErr:%d\n", iErr);
    }

    return;
}

static int StreamEncryptCBFunc (int iMsg, void* pParam)
{
    static FILE *fp = NULL;
    int iErr = ERR_COMMON_SUCCESS;

    switch (iMsg)
    {
        case MSG_CRYPT_DATA:
        case MSG_CRYPT_FINISH:
        {
            if (NULL == fp)
            {
  
                fp = fopen (ENCRYPTED_STREAM, "wb+");
                if (NULL == fp)
                {
                    iErr = ERR_COMMON_FILE_OPER_FAILED;
                    break;
                }
            }

            if (MSG_CRYPT_FINISH == iMsg)
            {
                fclose (fp);
                fp = NULL;
                break;
            }

            if (NULL == pParam)
            {
                iErr = ERR_COMMON_INVALID_PARAM;
                break;
            }

            CB_PARAM_S *pstParam = pParam;
            if (0 == pstParam->iParamLen)
            {
                break;
            }

            int iWriteLen = fwrite (pstParam->pcData, 1, pstParam->iParamLen, fp);
            if (iWriteLen < 0)
            {
                iErr = ERR_COMMON_FILE_OPER_FAILED;
                break;
            }
            break;
        }
        default:
        {
            break;
        }
    }

    return iErr;
}

static int StreamDecryptCBFunc (int iMsg, void* pParam)
{
    static FILE *fp = NULL;
    int iErr = ERR_COMMON_SUCCESS;

    switch (iMsg)
    {
        case MSG_CRYPT_DATA:
        case MSG_CRYPT_FINISH:
        {
            if (NULL == fp)
            {
                fp = fopen (DECRYPTED_STREAM, "wb+");
                if (NULL == fp)
                {
                    iErr = ERR_COMMON_FILE_OPER_FAILED;
                    break;
                }
            }

            if (MSG_CRYPT_FINISH == iMsg)
            {
                fclose (fp);
                fp = NULL;
                break;
            }

            if (NULL == pParam)
            {
                iErr = ERR_COMMON_INVALID_PARAM;
                break;
            }

            CB_PARAM_S *pstParam = pParam;
            if (0 == pstParam->iParamLen)
            {
                break;
            }

            int iWriteLen = fwrite (pstParam->pcData, 1, pstParam->iParamLen, fp);
            if (iWriteLen < 0)
            {
                iErr = ERR_COMMON_FILE_OPER_FAILED;
                break;
            }
            break;
        }
        default:
        {
            break;
        }
    }

    return iErr;
}
unsigned long long get_file_size(const char *path)  
{  
    unsigned long long udlFileSize = 0;

    if (NULL == path)
    {
        return udlFileSize;
    }

#ifdef WIN32
    struct _stat64 statbuf;
    if(_stat64(path, &statbuf) < 0)
    {  
        return udlFileSize;  
    }
    else
    {  
        udlFileSize = statbuf.st_size;  
    }  
#elif UNIX
    struct stat statbuf;  
    if(stat(path, &statbuf) < 0)
    {  
        return udlFileSize;  
    }
    else
    {  
        udlFileSize = statbuf.st_size;  
    }  
#elif APPLE
    struct stat statbuf;  
    if(stat(path, &statbuf) < 0)
    {  
        return udlFileSize;  
    }
    else
    {  
        udlFileSize = statbuf.st_size;  
    }  
#endif

    return udlFileSize;
}  

void stream_crypt (char *pcParam)
{
    CRYPT_HANDLE hCrypt = 0;
    CIPHER_STREAM_S stStreamCrypt;
    memset (&stStreamCrypt, 0, sizeof (stStreamCrypt));
    stStreamCrypt.pfCryptCBFunc = StreamEncryptCBFunc;


    META_S stMeta;
    memset (&stMeta, 0, sizeof (stMeta));
    snprintf (stMeta.szId, sizeof (stMeta.szId), "%s", "this is id");
    snprintf (stMeta.szOwner, sizeof (stMeta.szId), "%s", "this is owner");
    stMeta.iVersion = 1;
    stMeta.iBlockSize = 1024;
    stMeta.iOffLine = 1;

    snprintf (stMeta.stCipher.szAlgorithm, sizeof (stMeta.stCipher.szAlgorithm), "%s", "AES");
    snprintf (stMeta.stCipher.szMode, sizeof (stMeta.stCipher.szMode), "%s", "CFB");
    snprintf (stMeta.stCipher.szPadding, sizeof (stMeta.stCipher.szPadding), "%s", "NoPadding");
    snprintf ((char*) stMeta.stCipher.szKey, sizeof (stMeta.stCipher.szKey), "%s", "this is key");
    snprintf ((char*) stMeta.stCipher.szIv, sizeof (stMeta.stCipher.szIv), "%s", "this is Iv");

    stMeta.stThumb.iExistes = 1;
    stMeta.stThumb.iSize = 2048;

    printf ("stream encrypt \n");
    hCrypt = LOCKET_CIPHER_StreamEncryptInit(&stStreamCrypt, &stMeta);
    if (0 == hCrypt)
    {
        printf ("stream encrypt init failed\n");
        return;
    }

    FILE *fp = fopen (pcParam, "rb");
    if (NULL == fp)
    {
        printf ("open %s failed\n", pcParam);
        return;
    }

    int iReadLen = 0;
    char szReadBuffer[1024] = {0};
    int iLastBlock = 0;
    unsigned long long udlFileSize = get_file_size (pcParam);
    unsigned long long udlTotalLen = 0;
    while (1)
    {
        iReadLen = fread (szReadBuffer, 1, sizeof (szReadBuffer), fp);
        if (iReadLen < 0)
        {
            printf ("read failed\n");
            break;
        }
        else if (0 == iReadLen)
        {
            printf ("read eof\n");
            break;
        }
        udlTotalLen += iReadLen;
        if (udlTotalLen == udlFileSize)
        { 
            printf ("read last block\n");
            iLastBlock =  1;
        }

        int iErr = LOCKET_CIPHER_StreamEncryptUpdate (hCrypt, szReadBuffer, iReadLen, iLastBlock);
        if (ERR_COMMON_SUCCESS != iErr)
        {
            printf ("stream encrypt udpate failed\n");
            break;
        }
    }
    LOCKET_CIPHER_StreamCryptFree (hCrypt);
    fclose (fp);

    fp = fopen (ENCRYPTED_STREAM, "rb");
    if (NULL == fp)
    {
        printf ("open stream_encrypt.txt failed\n");
        return;
    }
    stStreamCrypt.pfCryptCBFunc = StreamDecryptCBFunc;
    printf ("stream decrypt \n");
    hCrypt = LOCKET_CIPHER_StreamDecryptInit(&stStreamCrypt);
    if (0 == hCrypt)
    {
        printf ("stream decrypt init failed\n");
        return;
    }

    int iErr =ERR_COMMON_SUCCESS;
    while (1)
    {
        iReadLen = fread (szReadBuffer, 1, sizeof (szReadBuffer), fp);
        if (iReadLen < 0)
        {
            printf ("read failed\n");
            break;
        }
        else if (0 == iReadLen)
        {
            printf ("1read eof\n");
            break;
        }

        iErr = LOCKET_CIPHER_StreamDecryptUpdate (hCrypt, szReadBuffer, iReadLen);
        if (ERR_STREAM_DECODE_FINISH == iErr)
        {
            iErr = ERR_COMMON_SUCCESS;
            break;
        }
        else if (ERR_STREAM_NEED_MORE_BITS  == iErr)
        {
            continue;
        }
        else if (ERR_COMMON_SUCCESS != iErr)
        {
            printf ("stream decrypt update failed, iErr:%d\n", iErr);
            break;
        }
    }
    
    fclose(fp);
    LOCKET_CIPHER_StreamCryptFree(hCrypt);


    return;
}

int main(int argc, char *argv[])
{
#ifdef WIN32
    printf ("current paltform is win32\n");
#elif APPLE
    printf ("current paltform is apple\n");
#elif UNIX
    printf ("current paltform is unix\n");
#else
    printf ("unkown platform\n");
#endif

    /* 初始化 */
    LOCKET_CIPHER_Init ();

    //buffer_crypt(argv[1]);

    file_crypt(argv[1]);

    stream_crypt(argv[1]);
    
#if 0
    int fd = open(argv[1],  O_RDWR|O_APPEND|O_CREAT|O_LARGEFILE, 0666);
    if (-1 == fd)
    {
        printf ("open file failed\n");
        return 0;
    }
#endif



    return 0;
}


